﻿using System;

namespace Eniux.SharpOpenGL
{
    /// <summary>
    /// DIBSection类型渲染上下文
    /// </summary>
    public class DIBSectionRenderContext : RenderContext
    {
        #region 变量

        /// <summary>
        /// DIBSection对象
        /// </summary>
        protected DIBSection dibSection = new DIBSection();

        #endregion

        #region 属性

        /// <summary>
        ///获取DIBSection
        /// </summary>
        public DIBSection DIBSection
        {
            get { return dibSection; }
        }

        #endregion

        #region 构造

        /// <summary>
        /// 默认构造
        /// </summary>
        public DIBSectionRenderContext()
        {
            //  We can layer GDI drawing on top of open gl drawing.
            GDIDrawingEnabled = true;
        } 

        #endregion

        #region 重写方法

        /// <summary>
        /// 创建渲染上下文
        /// </summary>
        /// <param name="gl">OpenGL上下文</param>
        /// <param name="width">宽度</param>
        /// <param name="height">高度</param>
        /// <param name="bitDepth">位深</param>
        /// <param name="parameter">参数</param>
        /// <returns>bool</returns>
        public override bool Create(OpenGL gl, int width, int height, int bitDepth, object parameter)
        {
            //  Call the base.
            base.Create(gl, width, height, bitDepth, parameter);

            //  Get the desktop DC.
            IntPtr desktopDC = Win32.GetDC(IntPtr.Zero);

            //  Create our DC as a compatible DC for the desktop.
            deviceContextHandle = Win32.CreateCompatibleDC(desktopDC);

            //  Release the desktop DC.
            Win32.ReleaseDC(IntPtr.Zero, desktopDC);

            //  Create our dib section.
            dibSection.Create(deviceContextHandle, width, height, bitDepth);

            //  Create the render context.
            Win32.wglMakeCurrent(IntPtr.Zero, IntPtr.Zero);
            renderContextHandle = Win32.wglCreateContext(deviceContextHandle);

            //  Make current.
            MakeCurrent();

            //  Return success.
            return true;
        }

        /// <summary>
        /// 销毁渲染上下文
        /// </summary>
        public override void Destroy()
        {
            //  Destroy the bitmap.
            dibSection.Destroy();

            //	Release the device context.
            Win32.ReleaseDC(IntPtr.Zero, deviceContextHandle);

            //	Call the base, which will delete the render context handle.
            base.Destroy();
        }

        /// <summary>
        ///设置渲染上下文尺寸.
        /// </summary>
        /// <param name="width">宽度</param>
        /// <param name="height">高度</param>
        public override void SetDimensions(int width, int height)
        {
            //  Call the base.
            base.SetDimensions(width, height);

            //	Resize.
            dibSection.Resize(width, height, BitDepth);
        }

        /// <summary>
        /// 将呈现位块的数据给上下文.
        /// </summary>
        /// <param name="hdc">The HDC.</param>
        public override void Blit(IntPtr hdc)
        {
            //  We must have a device context.
            if (deviceContextHandle != null)
            {
                //	Swap the buffers.
                Win32.SwapBuffers(deviceContextHandle);

                //  Blit to the device context.
                Win32.BitBlt(hdc, 0, 0, Width, Height, deviceContextHandle, 0, 0, Win32.SRCCOPY);
            }
        }

        /// <summary>
        /// 确定渲染当前上下文
        /// </summary>
        public override void MakeCurrent()
        {
            //  If we have a render context and DC make current.
            if (renderContextHandle != IntPtr.Zero && deviceContextHandle != IntPtr.Zero)
                Win32.wglMakeCurrent(deviceContextHandle, renderContextHandle);
        } 

        #endregion
    }
}
